Select(), Poll(), এবং Epoll() এর ব্যবহার

Computer Programming - ইউনিক্স সকেট (Unix Socket) Concurrency এবং Socket Programming (Concurrency in Socket Programming) |
254
254

select(), poll(), এবং epoll() হলো তিনটি গুরুত্বপূর্ণ সিস্টেম কল, যা নেটওয়ার্ক প্রোগ্রামিংয়ে I/O Multiplexing অর্জনের জন্য ব্যবহৃত হয়। এগুলোর মাধ্যমে একাধিক Socket বা File Descriptor-কে একসাথে পর্যবেক্ষণ করা যায় এবং এক বা একাধিক File Descriptor থেকে ইনপুট পাওয়া গেলে তা প্রক্রিয়া করা যায়। এগুলো বিশেষত নেটওয়ার্ক সার্ভার এবং উচ্চ-পারফরম্যান্স অ্যাপ্লিকেশন ডিজাইন করতে ব্যবহৃত হয়। নিচে প্রতিটি ফাংশনের ব্যবহার, প্রয়োজনীয়তা, এবং উদাহরণ দেওয়া হলো:

1. select()

select() একটি পুরনো এবং সাধারণ সিস্টেম কল, যা File Descriptor সেটগুলোকে (Sockets, Files, Pipes ইত্যাদি) পর্যবেক্ষণ করে। এটি নির্দিষ্ট File Descriptor-এ I/O অপারেশন করার জন্য প্রস্তুত কিনা তা চেক করে।

select() ফাংশনের সিগনেচার (C ভাষায়)

int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
  • nfds: সর্বোচ্চ File Descriptor এর মান + 1।
  • readfds: File Descriptor সেট যা Read অপারেশনের জন্য পর্যবেক্ষণ করা হবে।
  • writefds: File Descriptor সেট যা Write অপারেশনের জন্য পর্যবেক্ষণ করা হবে।
  • exceptfds: File Descriptor সেট যা Exceptional Condition এর জন্য পর্যবেক্ষণ করা হবে।
  • timeout: কত সময় অপেক্ষা করবে (একটি টাইমআউট ভ্যালু)।

select() এর উদাহরণ

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/select.h>
#include <arpa/inet.h>

#define PORT 8080

int main() {
    int server_fd, client_fd, max_fd, activity;
    struct sockaddr_in server_addr;
    fd_set read_fds;
    char buffer[1024];

    // Server socket তৈরি করা
    server_fd = socket(AF_INET, SOCK_STREAM, 0);
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port = htons(PORT);

    bind(server_fd, (struct sockaddr*)&server_addr, sizeof(server_addr));
    listen(server_fd, 3);

    while (1) {
        FD_ZERO(&read_fds);
        FD_SET(server_fd, &read_fds);
        max_fd = server_fd;

        // select() কল করা
        activity = select(max_fd + 1, &read_fds, NULL, NULL, NULL);

        if (activity > 0 && FD_ISSET(server_fd, &read_fds)) {
            client_fd = accept(server_fd, NULL, NULL);
            printf("New connection accepted\n");
            read(client_fd, buffer, sizeof(buffer));
            printf("Received: %s\n", buffer);
            close(client_fd);
        }
    }

    close(server_fd);
    return 0;
}

2. poll()

poll() হলো select()-এর একটি উন্নত সংস্করণ, যা একাধিক File Descriptor-কে পর্যবেক্ষণ করে এবং I/O অপারেশন করার জন্য প্রস্তুত কিনা তা জানায়। এটি select()-এর মতো কাজ করে, তবে এটি একটি Array ব্যবহার করে, যা select()-এর Fixed-Size Set-এর চেয়ে বেশি নমনীয়।

poll() ফাংশনের সিগনেচার (C ভাষায়)

int poll(struct pollfd *fds, nfds_t nfds, int timeout);
  • fds: struct pollfd এর একটি Array যা File Descriptor এবং তাদের Event টাইপ ধারণ করে।
  • nfds: Array-তে থাকা File Descriptor এর সংখ্যা।
  • timeout: কতক্ষণ অপেক্ষা করবে (মিলিসেকেন্ডে)।

poll() এর উদাহরণ

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <poll.h>
#include <arpa/inet.h>

#define PORT 8080

int main() {
    int server_fd, client_fd;
    struct sockaddr_in server_addr;
    struct pollfd fds[10];
    int nfds = 1;
    char buffer[1024];

    // Server socket তৈরি করা
    server_fd = socket(AF_INET, SOCK_STREAM, 0);
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port = htons(PORT);

    bind(server_fd, (struct sockaddr*)&server_addr, sizeof(server_addr));
    listen(server_fd, 3);

    fds[0].fd = server_fd;
    fds[0].events = POLLIN;

    while (1) {
        int activity = poll(fds, nfds, -1);

        if (activity > 0 && (fds[0].revents & POLLIN)) {
            client_fd = accept(server_fd, NULL, NULL);
            printf("New connection accepted\n");
            read(client_fd, buffer, sizeof(buffer));
            printf("Received: %s\n", buffer);
            close(client_fd);
        }
    }

    close(server_fd);
    return 0;
}

3. epoll()

epoll() হলো Linux-এ select() এবং poll() এর আরও উন্নত সংস্করণ, যা উচ্চ-পারফরম্যান্স অ্যাপ্লিকেশন এবং সার্ভারের জন্য উপযুক্ত। এটি স্কেলেবিলিটির জন্য ডিজাইন করা হয়েছে এবং অনেক বেশি File Descriptor পরিচালনা করতে সক্ষম। epoll() ব্যবহারের মাধ্যমে বেশিরভাগ ইভেন্ট-ড্রিভেন সার্ভার এবং অ্যাপ্লিকেশন তৈরি করা হয়।

epoll() ফাংশনের তিনটি প্রধান অংশ

epoll_create():

  • একটি epoll instance তৈরি করে।
int epoll_create(int size);

epoll_ctl():

  • File Descriptor গুলোকে epoll instance-এ যোগ, সরানো বা পরিবর্তন করতে ব্যবহৃত হয়।
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);

epoll_wait():

  • epoll instance-এর মধ্যে থাকা File Descriptor গুলোতে ইভেন্ট আছে কিনা তা চেক করে এবং এটি ইভেন্ট পাওয়া গেলে তাদের ফেরত দেয়।
int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);

epoll() এর উদাহরণ

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/epoll.h>
#include <arpa/inet.h>

#define PORT 8080
#define MAX_EVENTS 10

int main() {
    int server_fd, client_fd, epoll_fd;
    struct sockaddr_in server_addr;
    struct epoll_event ev, events[MAX_EVENTS];
    char buffer[1024];

    // Server socket তৈরি করা
    server_fd = socket(AF_INET, SOCK_STREAM, 0);
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port = htons(PORT);

    bind(server_fd, (struct sockaddr*)&server_addr, sizeof(server_addr));
    listen(server_fd, 3);

    // epoll instance তৈরি করা
    epoll_fd = epoll_create(1);
    ev.events = EPOLLIN;
    ev.data.fd = server_fd;
    epoll_ctl(epoll_fd, EPOLL_CTL_ADD, server_fd, &ev);

    while (1) {
        int num_events = epoll_wait(epoll_fd, events, MAX_EVENTS, -1);

        for (int i = 0; i < num_events; i++) {
            if (events[i].data.fd == server_fd) {
                client_fd = accept(server_fd, NULL, NULL);
                printf("New connection accepted\n");

                ev.events = EPOLLIN;
                ev.data.fd = client_fd;
                epoll_ctl(epoll_fd, EPOLL_CTL_ADD, client_fd, &ev);
            } else {
                int client_fd = events[i].data.fd;
                read(client_fd, buffer, sizeof(buffer));
                printf("Received: %s\n", buffer);
                close(client_fd);
                epoll_ctl(epoll_fd, EPOLL_CTL_DEL, client_fd, NULL);
            }
        }
    }

    close(server_fd);
    close(epoll_fd);
    return 0;
}

তুলনা: select(), poll(), এবং epoll()

বৈশিষ্ট্যselect()poll()epoll()
স্কেলেবিলিটিসীমিত (1024 FD-এর বেশি পরিচালনা করতে পারে না)উন্নত, কিন্তু select() এর মতো সমস্যা আছেউচ্চ স্কেলেবিলিটি, অনেক বেশি FD পরিচালনা করতে পারে
কর্মক্ষমতাধীর, কারণ এটি প্রতিটি কলের সময় সবকিছু স্ক্যান করেতুলনামূলকভাবে ধীরদ্রুত, কারণ এটি শুধুমাত্র Active FD-এর উপর কাজ করে
ব্যবহারিকতাছোট অ্যাপ্লিকেশনের জন্য উপযুক্তমধ্যম স্কেল অ্যাপ্লিকেশনের জন্যউচ্চ-পারফরম্যান্স এবং বড় অ্যাপ্লিকেশন এবং সার্ভারের জন্য
পোর্টেবিলিটিPOSIX মান সম্মত, অনেক সিস্টেমে সমর্থিতPOSIX মান সম্মত, অনেক সিস্টেমে সমর্থিতLinux নির্দিষ্ট
common.content_added_by
টপ রেটেড অ্যাপ

স্যাট অ্যাকাডেমী অ্যাপ

আমাদের অল-ইন-ওয়ান মোবাইল অ্যাপের মাধ্যমে সীমাহীন শেখার সুযোগ উপভোগ করুন।

ভিডিও
লাইভ ক্লাস
এক্সাম
ডাউনলোড করুন
Promotion